package com.lx.util.secure.algorithm.coder;

import com.lx.annotation.Note;
import com.lx.util.secure.Algorithm;

import java.nio.charset.StandardCharsets;

public class Hex implements Coder{
    private Hex() {}

    private static final Hex HEX = new Hex();

    public static Hex getCoder() {
        return HEX;
    }

    private static final char[] HEX_CODE = "0123456789abcdef".toCharArray();

    @Override
    public String encodeToString(byte[] bytes) {
        StringBuilder r = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            r.append(HEX_CODE[(b >> 4) & 0xF]);
            r.append(HEX_CODE[(b & 0xF)]);
        }
        return r.toString();
    }

    @Override
    public byte[] encode(byte[] bytes) {
        return encodeToString(bytes).getBytes(StandardCharsets.UTF_8);
    }

    @Override
    public byte[] encode(String data) {
        return encodeToString(data).getBytes(StandardCharsets.UTF_8);
    }

    @Override
    public String encodeToString(String data) {
        return encodeToString(data.getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public byte[] decode(String data) {
        int nChars = data.length();
        if (nChars % 2 != 0) {
            throw new IllegalArgumentException("Hex-encoded string must have an even number of characters");
        } else {
            byte[] result = new byte[nChars / 2];

            for (int i = 0; i < nChars; i += 2) {
                int msb = Character.digit(data.charAt(i), 16);
                int lsb = Character.digit(data.charAt(i + 1), 16);
                if (msb < 0 || lsb < 0) {
                    throw new IllegalArgumentException("Detected a Non-hex character at " + (i + 1) + " or " + (i + 2) + " position");
                }
                result[i / 2] = (byte) (msb << 4 | lsb);
            }
            return result;
        }
    }

    @Override
    public byte[] decode(byte[] bytes) {
        return decode(new String(bytes,StandardCharsets.UTF_8));
    }

    @Override
    public String decodeToString(byte[] bytes) {
        return new String(decode(bytes),StandardCharsets.UTF_8);
    }

    public String decodeToString (String data) {
        return new String(decode(data),StandardCharsets.UTF_8);
    }


}